package aaa.schedule;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;

import aaa.database.Database;
import aaa.exception.AAAException;
import android.os.AsyncTask;

public class UpdateManager extends AsyncTask<Void, Object, Void> implements ScheduleConstants {

	private static UpdateManager oldInstance ;

	private static UpdateManager instance = new UpdateManager() ;

	protected ArrayList<UpdateListener> listeners ;

	protected ArrayList<String> queue ;
	
	protected ArrayList<String[]> nameChange ;

	protected Hashtable<String, Integer> status ;

	public UpdateManager() {
		this(new ArrayList<UpdateListener>(), new ArrayList<String>(), new ArrayList<String[]>(), new Hashtable<String, Integer>()) ;
	}

	public UpdateManager(UpdateManager um) {
		this(um.listeners, um.queue, um.nameChange, um.status) ;
	}

	/**
	 * @param listeners
	 * @param queue
	 * @param status
	 */
	public UpdateManager(ArrayList<UpdateListener> listeners,
			ArrayList<String> queue, ArrayList<String[]> nameChange, 
			Hashtable<String, Integer> status) {
		super();
		this.listeners = listeners;
		this.queue = queue;
		this.nameChange = nameChange;
		this.status = status;
		this.execute() ;
	}

	public void addListener (UpdateListener listener) {
		this.listeners.add(listener) ;
	}

	public void removeListener (UpdateListener listener) {
		this.listeners.remove(listener) ;
	}

	public static UpdateManager getInstance () {
		return UpdateManager.instance ;
	}

	public static void resume () {
		UpdateManager.instance = new UpdateManager(UpdateManager.oldInstance) ;
		UpdateManager.oldInstance = null ;
	}
	
	protected static void sleep () {
		// Temporisation de 500ms
		try {
			Thread.sleep(500) ;
		} catch (InterruptedException e1) {
			long start = System.currentTimeMillis(), 
					current = System.currentTimeMillis() ;
			while (current - start < 500) current = System.currentTimeMillis() ;
		}// try
	}

	@Override
	protected Void doInBackground(Void... params) {
		while (this.listeners.isEmpty()) UpdateManager.sleep() ;
		int oldQueueSize = this.queue.size() ;
		while (!this.listeners.isEmpty()) {
			UpdateManager.sleep() ;
			
			if (this.queue.size() != oldQueueSize) {
				oldQueueSize = this.queue.size() ;
				this.publishProgress("unknown", "unknown") ;
			}// if
			
			for(String[] nameChange : this.nameChange) {
				this.publishProgress(nameChange[0], this.status.get(nameChange[0]), null, nameChange[1]) ;
			}// for
			
			for(Iterator<String> iter = this.queue.iterator(); iter.hasNext(); ) {
				String schedule = iter.next() ;
				try {
					//TODO Add internet connection test
					this.setScheduleStatus(schedule, STATUS_UPDATING) ;
//					Database db = new Database() ; ;
//					Schedule newS = db.getScheduleWithName(schedule) ;
//					newS.build() ;
//					Schedule oldS = db.getScheduleWithName(schedule) ;
//					oldS.build(db) ;
//					db.setLastModifSchedule(oldS.getName()) ;
					ScheduleUpdater updater = new GuidScheduleUpdater(null) ;
//					updater.compare(oldS, newS) ;
					updater.updateSchedule() ;
					this.setScheduleStatus(schedule, STATUS_UPDATED) ;
				} catch (AAAException e) {
					this.setScheduleStatus(schedule, STATUS_NOT_UPDATED, e) ;
				}// try
				iter.remove() ;
			}// for
		}// while
		UpdateManager.oldInstance = UpdateManager.instance ;
		UpdateManager.instance = null ;
		return null ;
	}

	@Override
	protected void onCancelled() {
		super.onCancelled() ;
	}

	@Override
	protected void onPostExecute(Void result) {
		super.onPostExecute(result);
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
	}

	@Override
	protected void onProgressUpdate(Object... values) {
		for(UpdateListener listener : this.listeners) {
			listener.onUpdate(values) ;
		}// for
	}

	public int getScheduleStatus(String scheduleName) {
		if (this.status.containsKey(scheduleName)) {
			return this.status.get(scheduleName) ;
		}// if
		return STATUS_OTHER ;
	}
	
	public void setScheduleStatus(String scheduleName, int newStatus, AAAException e) {
		this.status.put(scheduleName, newStatus) ;
		this.publishProgress(scheduleName, newStatus, e) ;
	}
	
	public void setScheduleStatus(String scheduleName, int newStatus) {
		this.setScheduleStatus(scheduleName, newStatus, null) ;
	}

	public void addQueue(String scheduleName) {
		this.status.put(scheduleName, STATUS_WAITING_FOR_UPDATE) ;
		this.queue.add(scheduleName) ;
	}

	public void addNameChange(String scheduleName, String newName) {
		this.nameChange.add(new String[]{scheduleName, newName}) ;
	}
	
	public Hashtable<String, Integer> getStatusC() {
		return status;
	}

}
